#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;    // 完成量
bool isvalid = false;

#ifndef INTERVAL
#define INTERVAL (2)
#endif

#ifndef FORK_CMD
#define FORK_CMD "ls"
#endif

#ifndef FORK_ARG
#define FORK_ARG ""
#endif

// #define FORK_CMD  "/tmp/ftunc -c /etc/frp_full.ini"

#ifdef MY_SIZE
int my_size =  MY_SIZE;
#else
int my_size =  0;
#endif
pid_t pid;
/*
 * 检查是否token有效
 * -1 无效
 * 0 有效
 */
bool is_valid_token()
{
    // FILE *pipe = popen("/usr/bin/python3 ./web/ftun_login.py", "r");
    FILE *pipe = popen("ftun_login", "r");
    char buffer[128];
    if (!pipe)
    {
        perror("popen");
        return false;
    }

    fgets(buffer, sizeof(buffer), pipe);
    if (strncmp("True", buffer, strlen("True")) == 0)
    {
        return true;
    }

    return false;
}

void kill_app(pid_t pid)
{
    printf("软件未注册或已到期,联系作者购买:\r\n");
    printf("\t邮件: egg-software@outlook.com\r\n");
    printf("\t软件支付方式: https://github.com/TeaAndEgg/ftun\r\n");

    pid_t *pids;
    int count;

    char strcmd[256];
    // char str1 = "pstree -p %d|";
    // char str2 = " grep -o '([0-9]\\+)' |";
    // char str3 = "awk -F '[()]' '{print $2}' | tr ' ' '\\n'";
    snprintf(strcmd, sizeof(strcmd),
             // "%s%s%s",
             "pstree -p %d| grep -o '([0-9]\\+)' | awk -F '[()]' '{print $2}' | tr ' ' '\\n'",
             pid);

    FILE *pipe = popen(strcmd, "r");
    char buffer[64];
    int len;

    len = 1;

    while (fgets(buffer, sizeof(buffer), pipe) != NULL)
    {
        if (atoi(buffer) != pid)
        {
            kill(atoi(buffer), SIGTERM);
        }
    }
    pclose(pipe);
}

void *thread_func(void *arg)
{
    while (1)
    {
        isvalid = false;
        sleep(INTERVAL * 3);
        pthread_mutex_lock(&mutex);
        if (isvalid == false)
        {
            kill_app(pid);
            pthread_mutex_unlock(&mutex);
            return 0;
        }
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}
void sigterm_handler(int sig)
{
    printf("Received SIGTERM signal\n");
    exit(0);
}


void pick_program(char *my, char *app, int start, int end) {
    FILE *fp_my, *fp_app;
    char buffer[1024];
    int bytes_read, bytes_written, total_bytes_written = 0;

    // 打开 my 文件
    fp_my = fopen(my, "rb");
    if (fp_my == NULL) {
        perror("Failed to open input file");
        return;
    }

    // 打开 app 文件
    fp_app = fopen(app, "wb");
    if (fp_app == NULL) {
        perror("Failed to open output file");
        fclose(fp_my);
        return;
    }

    // 定位到文件起始位置
    if (fseek(fp_my, start, SEEK_SET) != 0) {
        perror("Failed to seek input file");
        fclose(fp_my);
        fclose(fp_app);
        return;
    }

    // 读取并写入数据
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp_my)) > 0) {
        bytes_written = fwrite(buffer, 1, bytes_read, fp_app);
        if (bytes_written != bytes_read) {
            perror("Failed to write output file");
            fclose(fp_my);
            fclose(fp_app);
            return;
        }
        total_bytes_written += bytes_written;
        if (total_bytes_written >= end - start) {
            break;
        }
    }

    // 关闭文件
    fclose(fp_my);
    fclose(fp_app);
}

long get_file_size(const char* filename) {
    FILE* fp = fopen(filename, "rb");
    if (fp == NULL) {
        // 文件打开失败
        return -1;
    }
    if (fseek(fp, 0, SEEK_END) != 0) {
        // 移动文件指针失败
        fclose(fp);
        return -1;
    }
    long size = ftell(fp);
    fclose(fp);
    return size;
}
#include <sys/stat.h>
int add_exec_permission(const char* filename) {
    if (chmod(filename, S_IRUSR | S_IWUSR| S_IXUSR | S_IXGRP | S_IXOTH) != 0) {
        perror("Failed to add execute permission");
        return -1;
    }
    return 0;
}

int main(int argc, char **argv)
{    
    /*
    -DMY_SIZE=${B_SIZE} \
    -DINTERVAL=2 \
    -DFORK_CMD="\"/tmp/ftuns\"" \
    -DFORK_ARG="\"/tmp/ftuns -c /etc/frps_full.ini\""
    */

    // printf("app size %d\r\n", my_size);

    // int total_size = get_file_size("./ftunsd");
    int total_size = get_file_size(argv[0]);
    pick_program(argv[0], FORK_CMD, my_size, total_size);
    add_exec_permission(FORK_CMD);
    pid = fork();
    if (pid == 0)
    {
        // printf("child\r\n");
        // system("/tmp/ftuns -c /etc/frps_full.ini");
        system(FORK_ARG);
    }
    else
    {
        pthread_t tid;
        int ret = pthread_create(&tid, NULL, thread_func, NULL);
        if (ret == 0)
        {
            printf("Thread created successfully.\n");
        }
        else
        {
            perror("pthread_create");
            return -1;
        }

        sleep(1);
        // 读取文件等待错误
        while (1)
        {
            if (false == is_valid_token())
            {
                isvalid = false;
                pthread_join(tid, NULL);
                printf("Exit\r\n");
                sleep(5);
                exit(1);
            }
            else
            {
                pthread_mutex_lock(&mutex);
                isvalid = true;
                pthread_mutex_unlock(&mutex);
            }
            sleep(INTERVAL);
        }
        // pthread_join(tid, NULL);
    }
    return 0;
}